﻿

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Npgsql;

namespace rodzinka
{
    public partial class mainWindow : Form
    {
        user Uzytkownik = null , Admin = null;
        private Dictionary<String, String> configFile = new Dictionary<string,string>();
        private Dictionary<String, TabPage> PanelPages = new Dictionary<string, TabPage>();

        int przegladanyUzytkownik,przegladaneWydarzenie;
        controlSelector selector = new controlSelector();
        public mainWindow()
        {
            InitializeComponent();
            selector.insert("wejscie", ekranPowitalnyBledu);
            selector.insert("logowanie",ekranLogowaniaLogowanie);
            selector.insert("tworzeniekonta", ekranLogowaniaTworzeniaKonta);
            selector.insert("panel", Panel);
            PanelPages["profil"] = Panel.TabPages[0];
            PanelPages["aktualnyprofil"] = Panel.TabPages[1];
            PanelPages["szukajOsoby"] = Panel.TabPages[2];
            PanelPages["znajomi"] = Panel.TabPages[3];
            reconnect();
        }

        public void reconnect()
        {
            ekranPowitaniaPolacz_Click(null, null);
            loginError.Visible = false;
            ekrantworzeniaKontaBlad.Visible = false;
            loginTextBox.Text = "";
            passwordTextBox.Text = "";
            ekranTworzeniaKontaImie.Text = "";
            ekranTworzeniaKontaNazwisko.Text = "";
            ekranTworzeniaKontaAdres.Lines = null;
            Panel.TabPages.Clear();
        }

        public bool wczytajPlikKonfiguracyjny()
        {
            configFile.Clear();
            if (!File.Exists("config.cfg"))
            {
                ekranPowitalnyKomunikat.Text = "Brak pliku konfiguracyjnego (config.cfg)";
                File.Create("config.cfg").Close();
                return false;
            }
            StreamReader reader = File.OpenText("config.cfg");
            String s;
            while (reader.EndOfStream == false)
            {
                s=reader.ReadLine();
                String[] args = s.Split('=');
                if (args.Length != 2)
                {
                    ekranPowitalnyKomunikat.Text = "Błędny plik konfiguracyjny (config.cfg)";
                    reader.Close();
                    return false;
                }
                configFile[args[0].Trim()] = args[1].Trim();
            }
            reader.Close();
            return true;
        }

        private void loginButton_Click(object sender, EventArgs e)
        {
            try
            {
                Uzytkownik = new user("127.0.0.1", "5432", "rodzinka", loginTextBox.Text, passwordTextBox.Text);
            }
            catch 
            {
                loginError.Text = String.Format("Nieprawidłowy użytkownik bądź hasło");
                loginError.Visible = true;
                return;
            }
            if (Uzytkownik.userID != -1)
            {
                Panel.TabPages.Insert(0, PanelPages["profil"]);
                tabPage1_Enter(null, null);
            }
            selector.select("panel");


        }

        private void passwordTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode.Equals(Keys.Enter))
                loginButton_Click(sender, (EventArgs)e);
        }

        private void createAccountButton_Click(object sender, EventArgs e)
        {
            String login = loginTextBox.Text;
            String password = passwordTextBox.Text;
            if (login.Equals("") || password.Equals(""))
            {
                loginError.Text = String.Format("Musisz podać nazwe użytkownika i hasło");
                loginError.Visible = true;
            }
            else
            {
                if (Admin.userExist(login))
                {
                    loginError.Text = String.Format("Podany użytkownik istnieje");
                    loginError.Visible = true;
                }
                else
                {
                    loginError.Visible = false;
                    selector.select("tworzeniekonta");
                    ekrantworzeniaKontaBlad.Visible = false;
                    ekranLogowaniaTworzenieKontaPowitanie.Text = "Witaj " + login + " !\n" + "Wypełnij dane i ciesz się\nmożliwościami jakie daje Ci rodzinka";
                }
            }
        }

        private void ekranPowitaniaZapisz_Click(object sender, EventArgs e)
        {
            StreamWriter writer = File.CreateText("config.cfg");
            writer.WriteLine("host={0}", ekranPowitalnyHost.Text);
            writer.WriteLine("port={0}", ekranPowitalnyPort.Text);
            writer.WriteLine("dbName={0}", ekranPowitalnyDBName.Text);
            writer.Close();
        }

        private void ekranPowitaniaPolacz_Click(object sender, EventArgs e)
        {
            if (wczytajPlikKonfiguracyjny())
            {
                try
                {
                    ekranPowitalnyHost.Text = configFile["host"];
                    ekranPowitalnyPort.Text = configFile["port"];
                    ekranPowitalnyDBName.Text = configFile["dbName"];
                    Admin = new user(ekranPowitalnyHost.Text, ekranPowitalnyPort.Text, ekranPowitalnyDBName.Text, "rafal", "master");
                }
                catch
                {
                    ekranPowitalnyKomunikat.Text = "Nie udało się połączyć z serwerem";
                }
                if (Admin == null)
                    selector.select("wejscie");
                else
                    selector.select("logowanie");
            }
            else
                ekranPowitalnyBledu.Visible = true;
        }

        private void ekranTworzenieKontaPowrot_Click(object sender, EventArgs e)
        {
            reconnect();
        }

        private void ekranTworzeniaKontaZalozKonto_Click(object sender, EventArgs e)
        {
            String login = loginTextBox.Text;
            String password = passwordTextBox.Text;
            String imie = ekranTworzeniaKontaImie.Text, nazwisko = ekranTworzeniaKontaNazwisko.Text, adres = "";
            foreach (String s in ekranTworzeniaKontaAdres.Lines)
                adres += s + '\n';
            String dataUR = ekranTworzenieKontaData.Text;
            if (login == "" || password == "")
            {
                ekrantworzeniaKontaBlad.Text = "Błąd: musisz podać imie i nazwisko";
                ekrantworzeniaKontaBlad.Visible = true;
                return;
            }
            if (Admin.createUser(login, password, imie, nazwisko, dataUR, adres))
            {
                ekrantworzeniaKontaBlad.Text = "Gratulacje: założono konto";
                ekrantworzeniaKontaBlad.Visible = true;
            }
            else
                reconnect();

 
        }

        private void ProfilAktualizuj_Click(object sender, EventArgs e)
        {
            NpgsqlConnection connection = Admin.connection;
            try
            {
                connection.Open();
                String imie = ProfilImie.Text, nazwisko = ProfilNazwisko.Text, dataur = ProfilData.Text, adres = "";
                foreach (String s in ProfilAdres.Lines)
                    adres += s+'\n';
                //adres = String.Format("UPDATE osoba SET imie = '{0}',nazwisko = '{1}' , data_ur = '{2}' , adres = '{3}' where osoba_id = {4}", imie, nazwisko, dataur, adres, Uzytkownik.userID);
                NpgsqlCommand command = new NpgsqlCommand(String.Format("UPDATE osoba SET imie = '{0}',nazwisko = '{1}' , data_ur = '{2}' , adres = '{3}' where osoba_id = {4}", imie,nazwisko,dataur,adres,Uzytkownik.userID), connection);
                command.ExecuteNonQuery();
                connection.Close();
            }
            catch 
            {
                reconnect();
            }
        }


        private void tabPage1_Enter(object sender, EventArgs e)
        {
            NpgsqlConnection connection = Uzytkownik.connection;
            try
            {
                connection.Open();
                NpgsqlCommand command = new NpgsqlCommand(String.Format("select imie,nazwisko,data_ur,adres from osoba where osoba_id = '{0}'", Uzytkownik.userID), connection);
                NpgsqlDataReader reader = command.ExecuteReader();
                reader.Read();
                ProfilImie.Text = reader.GetString(0);
                ProfilNazwisko.Text = reader.GetString(1);
                ProfilData.Value = (DateTime)reader.GetDateTime(2);
                ProfilAdres.Lines = reader.GetString(3).Split('\n');
                reader.Close();
                connection.Close();
                ProfilZdjecie.Image = getImage(Uzytkownik.userID);
            }
            catch
            {
                reconnect();
            }
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            wyborZdjecia.ShowDialog();
        }

        private void wyborZdjecia_FileOk(object sender, CancelEventArgs e)
        {
            try
            {
                FileStream imageFile = new FileStream(wyborZdjecia.FileName, FileMode.Open, FileAccess.Read);
                BinaryReader imageReader = new BinaryReader(new BufferedStream(imageFile));
                Byte[] bytes = imageReader.ReadBytes((Int32)imageFile.Length);
                imageReader.Close();
                imageFile.Close();
                NpgsqlConnection connection = Admin.connection;
                connection.Open();
                NpgsqlCommand command = new NpgsqlCommand(String.Format("select dodajdanecyfrowe({0},'bierzace',:zdjecie)",Uzytkownik.userID), connection);
                NpgsqlParameter param = new NpgsqlParameter(":zdjecie", DbType.Binary);
                param.Value = bytes;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();
                connection.Close();
                ProfilZdjecie.Image = getImage(Uzytkownik.userID);
            }
            catch
            {
                reconnect();
            }
        }

        private void ProfilDodajZnajomego_Click(object sender, EventArgs e)
        {
            if (!Panel.TabPages.Contains(PanelPages["szukajOsoby"]))
                Panel.TabPages.Insert(Panel.TabPages.Count,PanelPages["szukajOsoby"]);
            Panel.SelectTab("szukajOsoby");
        }

        public Image getImage(int UserID)
        {
            NpgsqlConnection connection = Admin.connection;
            connection.Open();
            NpgsqlCommand command = new NpgsqlCommand(String.Format("select dane from (select * from osoba where osoba_id = {0}) JA natural join figuruje natural join dane_cyfrowe where rola = 'bierzace'", UserID),connection);
            byte[] image = (byte[])command.ExecuteScalar();
            Image ret = rodzinka.Properties.Resources.brakzdjecia;
            if (image != null)
                ret = Image.FromStream(new MemoryStream(image));
            connection.Close();
            return ret;
        }

        private void szukajOsobySzukaj_Click(object sender, EventArgs e)
        {
            try
            {
                String imie = szukajOsobeImie.Text, nazwisko = szukajOsobeNazwisko.Text, adres = "%";
                foreach (String s in szukajOsobeAdres.Lines)
                    adres += s + "%";
                if (imie == "")
                    imie = "%";
                if (nazwisko == "")
                    nazwisko = "%";
                NpgsqlConnection connection = Admin.connection;
                connection.Open();
                NpgsqlCommand command = new NpgsqlCommand(String.Format("select osoba_id,imie,nazwisko from osoba where imie like '{0}' and nazwisko like '{1}' and adres like '{2}'", imie, nazwisko, adres), connection);
                NpgsqlDataReader reader = command.ExecuteReader();
                List<object[]> uid = new List<object[]>();
                while (reader.Read())
                {
                    object[] usr = new object[3];
                    usr[0] = reader.GetInt32(0);
                    usr[1] = reader.GetString(1);
                    usr[2] = reader.GetString(2);
                    uid.Insert(uid.Count, usr);
                }
                connection.Close();
                szukajOsobLista.BeginUpdate();
                wyszukaneZdjecia.Images.Clear();
                szukajOsobLista.Items.Clear();
                szukajOsobLista.LargeImageList = wyszukaneZdjecia;
                int i=0;
                foreach (object[] usr in uid)
                {
                    wyszukaneZdjecia.Images.Add(getImage((int)usr[0]));
                    ListViewItem li = new ListViewItem((String)usr[1] + ' ' + (String)usr[2], i++);
                    li.SubItems.Add(((int)usr[0]).ToString());
                    szukajOsobLista.Items.Add(li);
                }
                szukajOsobLista.EndUpdate();
            }
            catch
            {
                reconnect();
            }

        }

        private void szukajOsobLista_DoubleClick(object sender, EventArgs e)
        {
            ListViewItem li = szukajOsobLista.SelectedItems[0];
            zaladujProfil(int.Parse(li.SubItems[1].Text));
        }

        private void zaladujProfil(int profilID)
        {
            try
            {
                przegladanyUzytkownik = profilID;
                if (!Panel.TabPages.Contains(PanelPages["aktualnyprofil"]))
                    Panel.TabPages.Add(PanelPages["aktualnyprofil"]);
                Panel.SelectTab(PanelPages["aktualnyprofil"]);
                NpgsqlConnection connection = Admin.connection;
                connection.Open();
                NpgsqlCommand command = new NpgsqlCommand(String.Format("select imie,nazwisko,data_ur,adres from osoba where osoba_id = {0}", profilID), connection);
                NpgsqlDataReader reader = command.ExecuteReader();
                if (reader.Read())
                {
                    aktualnyProfilImie.Text = reader.GetString(0);
                    aktualnyProfilNazwisko.Text = reader.GetString(1);
                    aktualnyProfilDataUr.Text = reader.GetDateTime(2).ToShortDateString();
                    aktualnyProfilAdres.Text = reader.GetString(3);
                }
                connection.Close();
                aktualnyProfilZdjecie.Image = getImage(profilID);
            }
            catch
            {
                reconnect();
            }

        }

        private void ZnajomiZakladka_Enter(object sender, EventArgs e)
        {
            try
            {
                NpgsqlConnection connection = Admin.connection;
                connection.Open();
                int userid = Uzytkownik.userID;
                NpgsqlCommand command = new NpgsqlCommand(String.Format("select Z.znajomy,O.imie,O.nazwisko from znajomy Z join osoba O on(znajomy=osoba_id) where ja = {0} order by Z.czas_dodania", userid), connection);
                NpgsqlDataReader reader = command.ExecuteReader();
                List<object[]> uid = new List<object[]>();
                while (reader.Read())
                {
                    object[] usr = new object[3];
                    usr[0] = reader.GetInt32(0);
                    usr[1] = reader.GetString(1);
                    usr[2] = reader.GetString(2);
                    uid.Insert(uid.Count, usr);
                }
                connection.Close();
                ZnajomiLista.BeginUpdate();
                ZnajomiZdjecia.Images.Clear();
                ZnajomiLista.Items.Clear();
                ZnajomiLista.LargeImageList = ZnajomiZdjecia;
                int i = 0;
                foreach (object[] usr in uid)
                {
                    ZnajomiZdjecia.Images.Add(getImage((int)usr[0]));
                    ListViewItem li = new ListViewItem((String)usr[1] + ' ' + (String)usr[2], i++);
                    li.SubItems.Add(((int)usr[0]).ToString());
                    ZnajomiLista.Items.Add(li);
                }
                szukajOsobLista.EndUpdate();
            }
            catch
            {
                reconnect();
            }
        }

        private void mojProfilPokazZnajomych_Click(object sender, EventArgs e)
        {
            if (!Panel.TabPages.Contains(PanelPages["znajomi"]))
                Panel.TabPages.Insert(Panel.TabPages.Count, PanelPages["znajomi"]);
            Panel.SelectTab(PanelPages["znajomi"]);
        }



    }

    public class controlSelector
    {
        private Dictionary<String, System.Windows.Forms.Control> selector = new Dictionary<string, System.Windows.Forms.Control>();
        System.Windows.Forms.Control selected = null;
        public void insert(String s, System.Windows.Forms.Control ctrl)
        {
            selector[s] = ctrl;
        }
        public void select(String s)
        {
            if (selected != null)
                selected.Visible = false;
            selected = selector[s];
            selected.Visible = true;
            selected.Dock = System.Windows.Forms.DockStyle.Fill;
        }
    }



    public class user
    {
        public NpgsqlConnection connection = new NpgsqlConnection();
        public int userID, userRole; //0 uzytkownik, 1 admin
        public user(String host,String port,String dbName,String login,String pass)
        {
            connection.ConnectionString = String.Format("Server={0};Port={1};User Id={2};Password={3};Database={4};",
                    host,port,login,pass,dbName);
            connection.Open();
            NpgsqlCommand command = new NpgsqlCommand(String.Format("select usename from pg_user where usename = '{0}'", login), connection);
            NpgsqlDataReader reader = command.ExecuteReader();
            if (!reader.HasRows)
                throw new Exception(String.Format("brak użytkownika {0} w bazie", login));
            userID = -1;
            userRole = 1;
            command.CommandText = String.Format("select osoba_id,typ from osoba where login = '{0}' LIMIT 1",login);
            reader.Close();
            reader = command.ExecuteReader();
            if (reader.HasRows)
            {
                reader.Read();
                userID = reader.GetInt32(0);
                userRole = reader.GetInt32(1);
            }
            connection.Close();
            
        }
        public bool userExist(String login)
        {
            connection.Open();
            NpgsqlCommand command = new NpgsqlCommand(String.Format("select rolname from pg_roles where rolname = '{0}'", login), connection);
            if (command.ExecuteScalar() == null)
            {
                connection.Close();
                return false;
            }
            connection.Close();
            return true;

        }
        public bool createUser(String login, String pass, String imie, String nazwisko, String dataUR, String adres)
        {
            connection.Open();
            String cmd = "BEGIN;";
            cmd += String.Format("INSERT INTO osoba(imie,nazwisko,login,data_ur) VALUES('{0}','{1}','{2}','{3}');", imie, nazwisko, login, dataUR);
            try
            {
                cmd+= String.Format(@"CREATE USER ""{0}"" WITH LOGIN PASSWORD '{1}' CONNECTION LIMIT 1 IN GROUP rafal;",login,pass);
                cmd += "end;";
                NpgsqlCommand command = new NpgsqlCommand(cmd,connection);
                command.ExecuteNonQuery();

            }
            catch
            {
                if (connection.State == ConnectionState.Open)
                {
                    NpgsqlCommand com = new NpgsqlCommand("rollback", connection);
                    com.ExecuteNonQuery();
                    connection.Close();
                }
                return false;
            }
            connection.Close();
            return true;
        }
    }


}
